home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-12-14 | 45.1 KB | 1,210 lines |
- *-----------------------------------------------------------------------
- *-- Program...: ARRAY.PRG
- *-- Programmer: Ken Mayer (CIS: 71333,1030)
- *-- Date......: 07/30/1993
- *-- Notes.....: These routines deal with filling arrays, sorting arrays,
- *-- and so on ... See README.TXT for details on using this
- *-- file.
- *-----------------------------------------------------------------------
-
- FUNCTION Afill
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 04/22/1992
- *-- Notes.......: Creates if needed, and fills a row or column of, an
- *-- array, with sequential numeric elements starting with
- *-- nFirst, increasing by nStep.
- *-- Useful for testing routines that require an array ...
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 03/01/1992 -- Original Release
- *-- 04/22/1992 - Jay Parsons - calling syntax changed
- *-- Calls.......: AMASK() Functon in ARRAY.PRG
- *-- Called by...: Any
- *-- Usage.......: AFill("<cArrayskel>",<nCount>,<nFirstVal>,<nStep>)
- *-- Example.....: lX = AFill("aTest",20,1,10)
- *-- Returns.....: .T. (and an array filled with values as in "notes"
- *-- above)
- *-- Parameters..: cArrayskel = Name of array and optional row/column
- *-- info
- *-- nCount = number of elements to fill
- *-- nFirstVal = starting value in array
- *-- nStep = number to increment by
- *-- Side effects: Creates as public, if needed, and fills array. Will
- *-- destroy existing array of the same name if its
- *-- dimensions are inadequate for the data to be filled
- *-- in.
- *-----------------------------------------------------------------------
-
- parameters cArrayskel, nCount, nFirstval, nStep
- private nAt, cArray, cMask, cElem, nRows, nCols, nFill
-
- m->cArray = m->cArrayskel
- if "[" $ m->cArray
- m->cArray = left( m->cArray, at( "[", m->cArray ) - 1 )
- endif
- m->cArray = trim( ltrim( m->cArray ) )
- m->cMask = Amask( m->cArrayskel, "nAt" )
- if at( ",", m->cMask ) > 0 .and. val( substr( m->cMask, ;
- at( ",", m->cMask ) + 1 ) ) = 0
- m->nRows = val( substr( m->cMask, at( "[", m->cMask ) + 1 ) )
- m->nCols = m->nCount
- else
- m->nRows = m->nCount
- m->nCols = val( substr( m->cMask, at( ",", m->cMask ) + 1 ) )
- endif
- m->nAt = m->nCount
- m->cElem = m->cArray + m->cMask
- if type( m->cElem ) = "U"
- release &cArray.
- public &cArray.
- if m->nCols > 0
- declare &cArray.[ m->nRows, m->nCols ]
- else
- declare &cArray.[ m->nRows ]
- endif
- endif
- m->nFill = m->nFirstVal
- m->nAt = 0
- do while m->nAt < m->nCount
- m->nAt = m->nAt + 1
- m->cElem = m->cArray + m->cMask
- store m->nFill to &cElem.
- m->nFill = m->nFill + m->nStep
- enddo
-
- RETURN .T.
- *-- EoF: Afill()
-
- FUNCTION Amask
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 04/21/1992
- *-- Notes.......: Returns a "mask" specifying the desired row or column
- *-- of an array.
- *-- Written for.: dBASE IV
- *-- Rev. History: 04/21/1992 -- Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Amask( <cArrayskel>, <cVar> )
- *-- Example.....: ? Amask( "Myarray [ , 1 ]", "nAt" )
- *-- Returns.....: A character value including a passed character string,
- *-- which may be used by the calling function to locate
- *-- array elements
- *-- Parameters..: cArrayskel = a character string including the name of
- *-- the array and, if the row or column to
- *-- be used is not the first row (or only
- *-- row if array is one-dimensional), a
- *-- bracketed expression with a number
- *-- indicating the row, or column if the
- *-- number is preceded by a comma, to be
- *-- used.
- *-- cVar = name of the memvar to be used by calling
- *-- function.
- *-----------------------------------------------------------------------
-
- parameters cArrayskel, cVar
- private nAt, cWhich, cMask, cV
-
- m->nAt = at( "[", m->cArrayskel )
- m->cWhich = "0 ]"
- m->cV = trim( ltrim( m->cVar ) )
- if m->nAt > 0
- m->cWhich = substr( m->cArrayskel, m->nAt + 1 )
- else
- m->cWhich = "1 ]"
- endif
- if .not. "," $ m->cArrayskel
- m->cMask = "[ " + m->cV + " ]"
- else
- if val( m->cWhich ) > 0
- m->cMask = "["+ ltrim( str( val( m->cWhich ) ) ) + "," +;
- m->cV + "]"
- else
- m->cWhich = substr( m->cWhich, at( ",", m->cWhich ) + 1 )
- m->cMask = "[" + m->cV+ ","+ ltrim( str( val( m->cWhich ) ) ) ;
- + "]"
- endif
- endif
-
- RETURN m->cMask
- *-- EoF: Amask()
-
- FUNCTION Amean
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 04/13/1992
- *-- Notes.......: Mean of non-blank numeric or date values in specified
- *-- row or column of a specified array. If the first
- *-- value is a date, averages only dates. If first value
- *-- is numeric or float, averages only numerics and
- *-- floats. Exits returning .F. if first value is
- *-- character or logical, if specified row or column does
- *-- not exist or if there are no averageable values.
- *-- Written for.: dBASE IV Version 1.5.
- *-- Rev. History: Original function written 1990
- *-- : Adapted to Version 1.5 4/13/1992
- *-- Calls.......: AMASK() Function in ARRAY.PRG
- *-- Called by...: Any
- *-- Usage.......: Amean( <cArrayskel> )
- *-- Example.....: ? Amean( "Myarray [ , 1 ]" )
- *-- Returns.....: A numeric, float or date value, the mean or average,
- *-- or .F. If any of the averaged items are floats, the
- *-- result will be.
- *-- Parameters..: cArrayskel = a character string including the name of
- *-- the array and, if the row or column to
- *-- be averaged is not the first row, a
- *-- bracketed expression with a number
- *-- indicating the row, or column if the
- *-- number is preceded by a comma, to be
- *-- averaged.
- *-----------------------------------------------------------------------
-
- parameters cArrayskel
- private nAt,cArray,cMask,cElem,nTot,nCount,xNext,cOktype
-
- m->cArray = m->cArrayskel
- if "[" $ m->cArray
- m->cArray = left( m->cArray, at( "[", m->cArray ) - 1 )
- endif
- m->cArray = trim( ltrim( m->cArray ) )
- m->cMask = Amask( m->cArrayskel, "nAt" )
- store 0 to m->nTot, m->nCount, m->nAt
- do while .t.
- m->nAt = m->nAt + 1
- m->cElem = m->cArray + m->cMask
- m->xNext = type( m->cElem )
- do case
- case m->xNext = "U"
- exit
- case m->nAt = 1
- if m->xNext $ "CL"
- exit
- else
- m->cOKType = iif( m->xNext = "D", "D", "NF" )
- endif
- case .not. m->xNext $ m->cOKType
- loop
- endcase
- m->xNext = &cElem.
- if isblank( m->xNext )
- loop
- endif
- if m->cOKType = "D"
- m->xNext = m->xNext - {01/01/01}
- endif
- m->nTot = m->nTot + m->xNext
- m->nCount = m->nCount + 1
- enddo
-
- RETURN iif( m->nCount = 0, .F., m->nTot / m->nCount ;
- + iif( m->cOKType = "D", {01/01/01}, 0 ) )
- *-- EoF: Amean()
-
- FUNCTION Amax
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 04/13/1992
- *-- Notes.......: Finds maximum non-blank numeric, date or character
- *-- value in specified row or column of a specified array.
- *-- If the first value is character or date, considers
- *-- only that type. If first value is numeric or float,
- *-- considers only numerics and floats. Exits returning
- *-- .F. if first value is logical, if specified row or
- *-- column does not exist or if there are no numeric,
- *-- date or character values in the row or column.
- *-- Written for.: dBASE IV Version 1.5.
- *-- Rev. History: Original function written 1990
- *-- : Adapted to Version 1.5 4/13/1992
- *-- Calls.......: AMASK() Function in ARRAY.PRG
- *-- Called by...: Any
- *-- Usage.......: Amax( <cArrayskel> )
- *-- Example.....: ? Amax( "Myarray [ , 1 ]" )
- *-- Returns.....: A char, numeric, float or date value, the maximum,
- *-- or .F. If any of the numeric items are floats, the
- *-- result will be.
- *-- Parameters..: cArrayskel = a character string including the name of
- *-- the array and, if the row or column to be
- *-- used is not the first row, a bracketed
- *-- expression with a number indicating the
- *-- row, or column if the number is preceded
- *-- by a comma, to be used.
- *-----------------------------------------------------------------------
-
- parameters cArrayskel
- private nAt,cArray,cMask,cElem,xMax,xNext,cOktype
-
- m->cArray = m->cArrayskel
- if "[" $ m->cArray
- m->cArray = left( m->cArray, at( "[", m->cArray ) - 1 )
- endif
- m->cArray = trim( ltrim( m->cArray ) )
- m->cMask = Amask( m->cArrayskel, "m->nAt" )
- store 0 to m->nAt
- do while .T.
- m->nAt = m->nAt + 1
- m->cElem = m->cArray + m->cMask
- m->xNext = type( m->cElem )
- do case
- case m->xNext = "U"
- exit
- case m->nAt = 1
- if m->xNext ="L"
- exit
- else
- m->cOKType = iif( m->xNext $ "CD", m->xNext, "NF" )
- endif
- case .not. m->xNext $ m->cOKType
- loop
- endcase
- m->xNext = &cElem.
- if m->cOKType # "C" .and. isblank( m->xNext )
- loop
- endif
- if m->nAt = 1
- m->xMax = m->xNext
- else
- m->xMax = max( m->xMax, m->xNext )
- endif
- enddo
-
- RETURN iif( type( "xMax" ) = "U", .F., m->xMax )
- *-- EoF: Amax()
-
- FUNCTION Amin
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 04/13/1992
- *-- Notes.......: Finds minimum non-blank numeric, date or character
- *-- value in specified row or column of a specified array.
- *-- If the first value is character or date, considers
- *-- only that type. If first value is numeric or float,
- *-- considers only numerics and floats. Exits returning
- *-- .F. if first value is logical, if specified row or
- *-- column does not exist or if there are no numeric,
- *-- date or character values in the row or column.
- *-- Written for.: dBASE IV Version 1.5.
- *-- Rev. History: Original function written 1990
- *-- : Adapted to Version 1.5 4/13/1992
- *-- Calls.......: AMASK() Function in ARRAY.PRG
- *-- Called by...: Any
- *-- Usage.......: Amin( <cArrayskel> )
- *-- Example.....: ? Amin( "Myarray [ , 1 ]" )
- *-- Returns.....: A char, numeric, float or date value, the minimum,
- *-- or .F. If any of the numeric items are floats,
- *-- the result will be.
- *-- Parameters..: cArrayskel = A character string including the name of
- *-- the array and, if the row or column to be
- *-- used is not the first row, a bracketed
- *-- expression with a number indicating the
- *-- row, or column if the number is preceded
- *-- by a comma, to be used.
- *-----------------------------------------------------------------------
-
- parameters cArrayskel
- private nAt,cArray,cMask,m->cElem,xMin,xNext,cOktype
-
- m->cArray = m->cArrayskel
- if "[" $ m->cArray
- m->cArray = left( m->cArray, at( "[", m->cArray ) - 1 )
- endif
- m->cArray = trim( ltrim( m->cArray ) )
- m->cMask = Amask( m->cArrayskel, "nAt" )
- store 0 to m->nAt
- do while .T.
- m->nAt = m->nAt + 1
- m->cElem = m->cArray + m->cMask
- m->xNext = type( m->cElem )
- do case
- case m->xNext = "U"
- exit
- case m->nAt = 1
- if m->xNext ="L"
- exit
- else
- m->cOKType = iif( m->xNext $ "CD", m->xNext, "NF" )
- endif
- case .not. m->xNext $ m->cOKType
- loop
- endcase
- m->xNext = &cElem.
- if m->cOKType # "C" .and. isblank( m->xNext )
- loop
- endif
- if m->nAt = 1
- m->xMin = m->xNext
- else
- m->xMin = min( m->xMin, m->xNext )
- endif
- enddo
-
- RETURN iif( type( "xMin" ) = "U", .F., m->xMin )
- *-- EoF: Amin()
-
- FUNCTION Avar
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 04/13/1992
- *-- Notes.......: Finds population variance of non-blank numeric or date
- *-- values in specified row or column of a specified
- *-- array. If first value is date, considers only that
- *-- type. If first value is numeric or float, considers
- *-- only numerics and floats. Exits returning .F. if
- *-- first value is character or logical, if specified
- *-- row or column does not exist or if there are no
- *-- numeric or date values in the row or column.
- *--
- *-- To adapt this to find the sample variance, substitute
- *-- "( nCount - 1 )" for the final "nCount" in the last
- *-- line.
- *-- Written for.: dBASE IV Version 1.5.
- *-- Rev. History: Original function written 1990
- *-- Adapted to Version 1.5 4/13/1992
- *-- Calls.......: AMASK() Function in ARRAY.PRG
- *-- Called by...: Any
- *-- Usage.......: Avar( <cArrayskel> )
- *-- Example.....: ? Avar( "Myarray [ , 1 ]" )
- *-- Returns.....: A numeric, or float value, the variance, or .F. If
- *-- any of the numeric items are floats, the result will
- *-- be.
- *-- Parameters..: cArrayskel = a character string including the name of
- *-- the array and, if the row or column to
- *-- be used is not the first row, a bracketed
- *-- expression with a number indicating the
- *-- row, or column if the number is preceded
- *-- by a comma, to be used.
- *-----------------------------------------------------------------------
-
- parameters cArrayskel
- private nAt,cArray,cMask,cElem,nCount,nTot,nTotsq,xNext,cOktype
-
- m->cArray = m->cArrayskel
- if "[" $ m->cArray
- m->cArray = left( m->cArray, at( "[", m->cArray ) - 1 )
- endif
- m->cArray = trim( ltrim( m->cArray ) )
- m->cMask = Amask( m->cArrayskel, "nAt" )
- store 0 to m->nTot, m->nTotsq, m->nCount, m->nAt
- do while .t.
- m->nAt = m->nAt + 1
- m->cElem = m->cArray + m->cMask
- m->xNext = type( m->cElem )
- do case
- case m->xNext = "U"
- exit
- case m->nAt = 1
- if m->xNext $ "CL"
- exit
- else
- m->cOKType = iif( m->xNext = "D", "D", "NF" )
- endif
- case .not. m->xNext $ m->cOKType
- loop
- endcase
- m->xNext = &cElem.
- if isblank( m->xNext )
- loop
- endif
- if m->cOKType = "D"
- m->xNext = m->xNext - {01/01/01}
- endif
- m->nTot = m->nTot + m->xNext
- m->nTotsq = m->nTotsq + m->xNext * m->xNext
- m->nCount = m->nCount + 1
- enddo
-
- RETURN iif( m->nCount = 0, .F., ( m->nTotsq - m->nTot * m->nTot / ;
- m->nCount ) / m->nCount )
- *-- EoF: Avar()
-
- FUNCTION Aseek
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 11/02/1993
- *-- Notes.......: Binary search of an array for an element of which the
- *-- value is Finditem (could be character, numeric or
- *-- date, but of course types of all elements must match).
- *-- Works only if array is sorted ascending. Element found
- *-- is not necessarily the first that matches the value
- *-- sought. To use with array sorted descending, change
- *-- ">" to "<" in the remarked line.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 03/01/1992 - original function.
- *-- 04/21/1992 - Jay Parsons - calling syntax changed
- *-- 11/02/1993 - now supports Version 2.0 large arrays
- *-- Calls.......: AMASK() Function in ARRAY.PRG
- *-- Called by...: Any
- *-- Usage.......: Aseek(<cArrayskel>,<xFindItem> )
- *-- Example.....: nIndex = Aseek("MyArray [ ,2 ], {01/15/89} )
- *-- Returns.....: numeric ( index to place in array where item exists,
- *-- or 0 )
- *-- Parameters..: cArrayskel = name of array and optional row/column
- *-- info
- *-- xFindItem = Item to look for in array. Must be same
- *-- TYPE as item in array looked for.
- *-- Numerics are NOT the same as floats for
- *-- this one.
- *-----------------------------------------------------------------------
-
- parameters cArrayskel, xFinditem
- private cArray, cMask, cElem, nHi, nLo, nTrial, cOktype
-
- m->cArray = m->cArrayskel
- if "[" $ m->cArray
- m->cArray = left( m->cArray, at( "[", m->cArray ) - 1 )
- endif
- m->cArray = trim( ltrim( m->cArray ) )
- m->cMask = Amask( m->cArrayskel, "nTrial" )
- m->cOKType = type( "xFinditem" )
- m->nLo = 1
- m->nHi = iif( val( substr( version(), 11, 3 ) ) < 2, 1170, 65535 )
- do while .t.
- if m->nHi < m->nLo
- m->nTrial = 0
- exit
- else
- m->nTrial = int( ( m->nHi + m->nLo ) / 2 )
- endif
- m->cElem = m->cArray + m->cMask
- m->xNext = type( m->cElem )
- do case
- case m->xNext = "U"
- m->nHi = m->nTrial - 1
- case .not. m->xNext $ m->cOKType
- m->nTrial = 0
- exit
- otherwise
- m->xNext = &cElem.
- do case
- case m->xNext = m->xFindItem
- exit
- case m->xNext > m->xFindItem && see notes
- m->nHi = m->nTrial - 1
- otherwise
- m->nLo = m->nTrial + 1
- endcase
- endcase
- enddo
-
- RETURN m->nTrial
- *-- EoF: Aseek
-
- FUNCTION Ashuffle
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 03/01/1992
- *-- Notes.......: Random shuffle of elements of an array
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 03/01/1992 -- Original Release
- *-- Calls.......: Amask() Function in ARRAY.PRG
- *-- Arrayrows() Function in ARRAY.PRG
- *-- Arraycols() Function in ARRAY.PRG
- *-- Called by...: Any
- *-- Usage.......: AShuffle( "<cArrayskel>" )
- *-- Example.....: lX = AShuffle( "aTest[ ,2]" )
- *-- Returns.....: .T.
- *-- Parameters..: cArrayskel = Name of array, optional row/column
- *-- designator
- *-- Side effects: Rearranges elements of the array
- *-- Reseeds random number generator and uses some random
- *-- numbers
- *-----------------------------------------------------------------------
-
- parameters cArrayskel
- private cArray, cMask, m->cElem, cElem, nAt, nRand, nLeft, x1, x2
-
- m->cArray = m->cArrayskel
- if "[" $ m->cArray
- m->cArray = left( m->cArray, at( "[", m->cArray ) - 1 )
- endif
- m->cArray = trim( ltrim( m->cArray ) )
- m->cMask = Amask( m->cArrayskel, "nAt" )
- if at( ",", m->cMask ) > 0 .and. val( substr( m->cMask, ;
- at( ",", m->cMask ) + 1 ) ) = 0
- m->nLeft = Arraycols( m->cArray )
- else
- m->nLeft = Arrayrows( m->cArray )
- endif
- m->nRand = rand( -1 )
- do while m->nLeft > 1
- m->nAt = m->nLeft
- m->cElem = m->cArray + m->cMask
- m->x1 = &cElem.
- m->nAt = int( rand() * m->nLeft ) + 1
- m->cElem = m->cArray + m->cMask
- m->x2 = &cElem.
- store m->x1 to &cElem.
- m->nAt = m->nLeft
- m->cElem = m->cArray + m->cMask
- store m->x2 to &cElem.
- m->nLeft = m->nLeft - 1
- enddo
-
- RETURN .T.
- *-- EoF: Ashuffle()
-
- FUNCTION Abubble
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 04/21/1992
- *-- Notes.......: Bubble sort. This is a slow algorithm, made slower by
- *-- passing the array name as a parameter instead of
- *-- copying the array to one of predefined name. Its
- *-- primary use is in selecting a few of the highest or
- *-- lowest values from a longer list. The argument
- *-- "nPasses" gives the number of values guaranteed to
- *-- be in their correct places, in this case the lowest
- *-- values, at the head of the list. Values at other
- *-- places in the list may not have been sorted.
- *-- Note: To place the highest values at the head of
- *-- the list, change > to < in the remarked line.
- *-- What use is it? Well, a golf handicap is based on
- *-- the lowest 10 score differentials of the last 20.
- *-- This is the easy way to select them. Other
- *-- applications include selecting a few invidividuals
- *-- from a large number of candidates based on some
- *-- numeric expression.
- *-- Written for.: dBASE IV, 1.1, 1.5
- *-- Rev. History: 04/21/1992 -- Original Release
- *-- Calls.......: AMASK() Function in ARRAY.PRG
- *-- Arraycols() Function in ARRAY.PRG
- *-- Arrayrows() Function in ARRAY.PRG
- *-- Called by...: Any
- *-- Usage.......: BubbleSort("<cArrayskel>" [,<nPass>] )
- *-- Example.....: lX = BubbleSort("Test [1,]",10)
- *-- Returns.....: .T.
- *-- Parameters..: cArrayskel = Name of array, optional row/column
- *-- designator
- *-- nPasses = number of passes. If you want a complete
- *-- sort, set this value to the same as
- *-- length of array, or omit it in 1.5.
- *-- Side effects: Rearranges elements of the array
- *-----------------------------------------------------------------------
-
- parameters cArrayskel, nPasses
- private nJ, nAt, cArray, cMask, cElem, x1, x2, nP, nPasses, lSwitch, ;
- nOld, nNew
-
- m->cArray = m->cArrayskel
- if "[" $ m->cArray
- m->cArray = left( m->cArray, at( "[", m->cArray ) - 1 )
- endif
- m->cArray = trim( ltrim( m->cArray ) )
- m->cMask = Amask( m->cArrayskel, "nAt" )
- if at( ",", m->cMask ) > 0 .and. val( substr( m->cMask, ;
- at( ",", m->cMask ) + 1 ) ) = 0
- m->nJ = Arraycols( m->cArray )
- else
- m->nJ = Arrayrows( m->cArray )
- endif
- if val( substr( version(), 9, 5 ) ) < 1.5 .or. pcount() > 1
- m->nP = min( m->nPasses, m->nJ )
- else
- m->nP = m->nJ
- endif
- m->nPass = 1
- do while m->nPass <= m->nP
- m->lSwitch = .F.
- m->nOld = m->nJ
- do while .t.
- m->cElem = m->cArray + m->cMask
- m->nAt = m->nOld
- m->x1 = &cElem.
- do while .t.
- m->nNew = m->nOld - 1
- if m->nNew < m->nPass
- exit
- endif
- m->nAt = m->nNew
- m->cElem = m->cArray + m->cMask
- m->x2 = &cElem.
- if m->x1 < m->x2 && see notes
- m->lSwitch = .T.
- m->nAt = m->nOld
- m->cElem = m->cArray + m->cMask
- store m->x2 to &cElem.
- m->nOld = m->nNew
- else
- exit
- endif
- enddo
- m->nAt = m->nOld
- m->cElem = m->cArray + m->cMask
- store m->x1 to &cElem.
- m->nOld = m->nNew
- if m->nOld <= m->nPass
- exit
- endif
- enddo
- if .not. m->lSwitch
- exit
- endif
- m->nPass = m->nPass + 1
- enddo
-
- RETURN .T.
- *-- EoF: Abubble()
-
- FUNCTION ArrayRows
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 03/24/1993
- *-- Notes.......: Number of Rows in an array
- *-- Written for.: dBASE IV, 1.1 to 2.0
- *-- Rev. History: 03/01/1992 -- Original
- *-- 03/24/1993 -- Modified to allow up to 65,535 elements
- *-- per dimension, as allowed by version
- *-- 2.0.
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: ArrayRows("<aArray>")
- *-- Example.....: n = ArrayRows("aTest")
- *-- Returns.....: numeric
- *-- Parameters..: aArray = Name of array
- *-----------------------------------------------------------------------
-
- parameters aArray
- private nHi, nLo, nTrial, nDims
-
- m->nLo = 1
- m->nHi = iif( val( substr( version(), 11, 3 ) ) < 2, 1170, 65535 )
- if type( "&aArray.[ 1, 1 ]" ) = "U"
- m->nDims = 1
- else
- m->nDims = 2
- endif
- do while .T.
- m->nTrial = int( ( m->nHi + m->nLo ) / 2 )
- if m->nHi < m->nLo
- exit
- endif
- if m->nDims = 1 .and. type( "&aArray.[ m->nTrial ]" ) = "U" .or.;
- m->nDims = 2 .and. type( "&aArray.[ m->nTrial, 1 ]" ) = "U"
- m->nHi = m->nTrial - 1
- else
- m->nLo = m->nTrial + 1
- endif
- enddo
-
- RETURN m->nTrial
- *-- EoF: ArrayRows()
-
- FUNCTION ArrayCols
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 03/24/1993
- *-- Notes.......: Number of Columns in an array
- *-- Written for.: dBASE IV, 1.1 to 2.0
- *-- Rev. History: 03/01/1992 Original function
- *-- 03/24/1993 Modified to allow up to 65,535 elements
- *-- per dimension, as allowed by dBASE IV
- *-- Version 2.0
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: ArrayCols("<aArray>")
- *-- Example.....: n = ArrayCols("aTest")
- *-- Returns.....: numeric
- *-- Parameters..: aArray = Name of array
- *-----------------------------------------------------------------------
-
- parameters aArray
- private nHi, nLo, nTrial
-
- m->nLo = 1
- m->nHi = iif( val( substr( version(), 11, 3 ) ) < 2, 1170, 65535 )
- if type( "&aArray.[ 1, 1 ]" ) = "U"
- RETURN 0
- endif
- do while .t.
- m->nTrial = int( ( m->nHi + m->nLo ) / 2 )
- if m->nHi < m->nLo
- exit
- endif
- if type( "&aArray.[ 1, m->nTrial ]" ) = "U"
- m->nHi = m->nTrial - 1
- else
- m->nLo = m->nTrial + 1
- endif
- enddo
-
- RETURN m->nTrial
- *-- EoF: ArrayCol()
-
- FUNCTION ShellSort
- *-----------------------------------------------------------------------
- *-- Programmer..: Jay Parsons (CIS: 72662,1302)
- *-- Date........: 11/28/1993
- *-- Notes.......: Sort aMyarray[] elements 1 to nNumber, ascending
- *-- Note: change < to > in the remarked line for
- *-- a descending sort.
- *-- If the array is two-dimensional, this sort moves all
- *-- elements of each row to whatever row is needed to put
- *-- the first column of the array into sorted order.
- *-- This routine depends on the elements being copied
- *-- into the array "aMyarray" before the sort. It could,
- *-- like the other array functions, accept the name of
- *-- the array as a parameter and use it as a macro within,
- *-- but performance will be very slow in that case.
- *-- Written for.: dBASE IV, 1.1
- *-- Rev. History: 03/01/1992 - Original Release
- *-- 06/15/1993 - Angus Scott-Fleming [75500,3223]
- *-- sorting a two-dimensional array
- *-- 11/28/1993 - Jay Parsons. Combined code for one- and
- *-- two-dimensional arrays to sort either
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: ShellSort(<nNumber>,[<nCols>])
- *-- Example.....: lX = ShellSort(532)
- *-- Returns.....: .T.
- *-- Parameters..: nNumber = Size of array (# of rows )
- *-- nCols = Size of array (# of columns ) [optional]
- *-----------------------------------------------------------------------
-
- parameters nNumber, nCols
- private nInterval, nPlace, nI, nJ, xTemp, nX
-
- m->nInterval = m->nNumber
- if type( "aMyarray[ 1, 1 ]" ) = "U"
- do while m->nInterval > 0
- nInterval = int( m->nInterval / 2 )
- nPlace = 1
- do while .T.
- nI = m->nPlace
- nJ = m->nI + m->nInterval
- if m->nJ > m->nNumber
- exit
- endif
- xTemp = aMyarray[ m->nJ ]
- do while m->xTemp < aMyarray[ m->nI ] && see note
- aMyarray[ m->nJ ] = aMyarray[ m->nI ]
- nJ = m->nI
- nI = m->nI - m->nInterval
- if m->nI < 1
- exit
- endif
- enddo
- aMyarray[ m->nJ ] = m->xTemp
- nPlace = m->nPlace + 1
- enddo
- enddo
- else
- if .not.(type("nCols")="N")
- m->nCols = 1
- endif
- declare xTemp[m->nCols]
- m->nInterval = m->nNumber
- do while m->nInterval > 0
- m->nInterval = int( m->nInterval / 2 )
- m->nPlace = 1
- do while .T.
- m->nI = m->nPlace
- m->nJ = m->nI + m->nInterval
- if m->nJ > m->nNumber
- exit
- endif
- m->nX = 0
- do while m->nX < m->nCols
- m->nX = m->nX + 1
- xTemp[m->nX] = aMyarray[ m->nJ, m->nX ]
- enddo
- do while xTemp[1] < aMyarray[ m->nI, 1 ] && see note
- m->nX = 0
- do while m->nX < m->nCols
- m->nX = m->nX + 1
- aMyarray[ m->nJ, m->nX ] = aMyarray[ m->nI, m->nX ]
- enddo
- m->nJ = m->nI
- m->nI = m->nI - m->nInterval
- if m->nI < 1
- exit
- endif
- enddo
- m->nX = 0
- do while m->nX < m->nCols
- m->nX = m->nX + 1
- aMyarray[ m->nJ, m->nX ] = xTemp[m->nX]
- enddo
- m->nPlace = m->nPlace + 1
- enddo
- enddo
- endif
-
- RETURN .T.
- *-- EoF: ShellSort()
-
- FUNCTION aPullSort
- *-----------------------------------------------------------------------
- *-- Programmer..: Kelvin Smith (KELVIN)
- *-- Date........: 05/07/1992
- *-- Notes.......: Sort aMyarray[] elements 1 to Number, ascending
- *-- Note: change > to < in the remarked line for
- *-- a descending sort.
- *-- This sorting algorithm, while not as fast as a shell
- *-- sort, is fairly simple to understand and considerably
- *-- faster than the infamous bubble sort. Each iteration
- *-- pulls the next item in order to the front of the
- *-- unsorted portion of the list.
- *-- This routine depends on the elements being copied
- *-- into the array "aMyarray" before the sort. It could,
- *-- like the other array functions, accept the name of
- *-- the array as a parameter and use it as a macro within,
- *-- but performance will be very slow in that case.
- *-- Written for.: dBASE IV, 1.5
- *-- Rev. History: 05/07/1992 -- Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: APullSort(<nNumber>)
- *-- Example.....: lX = APullSort(532)
- *-- Returns.....: .T.
- *-- Parameters..: nNumber = Size of array (# of elements)
- *-----------------------------------------------------------------------
-
- parameters nNumber
- private nI, nJ, nSwap, xTemp
-
- m->nI = 1
- do while m->nI < m->nNumber && Through the list
- m->nSwap = m->nI
- m->nJ = m->nI + 1
- do while m->nJ <= m->nNumber && From nI to end of list
- if aMyarray[m->nSwap] > aMyarray[m->nJ] && see note
- m->nSwap = m->nJ && Item at nJ is smaller
- endif
- m->nJ = m->nJ + 1
- enddo
- if m->nSwap <> m->nI && Found a smaller one
- m->xTemp = aMyarray[m->nSwap] && Swap it
- aMyarray[m->nSwap] = aMyarray[m->nI]
- aMyarray[m->nI] = m->xTemp
- endif
- m->nI = m->nI + 1
- enddo
-
- RETURN .T.
- *-- EoF: APullSort()
-
- PROCEDURE CmpArray
- *-----------------------------------------------------------------------
- *-- Programmer..: Werner Borsbach (CIS:100010,2236)
- *-- Date........: 02/09/93
- *-- Notes.......: Compares two arrays, returns the variable UNCHANGED
- *-- and an array GLEICH with the unchanged-value for every
- *-- field in case you have defined them before
- *-- calling or have set them public
- *-- Could easy be tranlated to a FUNCTION
- *-- Written for.: dBASE IV v1.5
- *-- Rev. History: 02/09/1993 Original Release
- *-- 05/16/1993 modified for use with - modified -
- *-- aRec2Arr()
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: do CmpArray with <Array1>,<Array2>,<Arindex>
- *-- Example.....: SatzNr=recno()
- *-- aRec2Arr("Test1")
- *-- edit SatzNr
- *-- goto Satznr
- *-- aRec2Arr("Test2")
- *-- unchanged=.t. (or public unchanged)
- *-- do Cmparray with "Test1","Test2",fldcount()
- *-- ? unchanged
- *-- Returns.....: unchanged and Array gleich if predefined
- *-- Parameters..: Array1 = Name of first array
- *-- Array2 = Name of second array
- *-- Arindex= Number of fields
- *-----------------------------------------------------------------------
-
- parameter array1,array2,arindex
-
- declare aGleich[m->ArIndex]
- m->lUnChanged=.t.
- m->nOrgInd=m->nArIndex
-
- do while m->nArIndex<>0
- aGleich[m->nArIndex]=iif(&array1.[m->nArIndex]=;
- &array2.[m->nArIndex],.t.,.f.)
- m->lUnChanged=iif(.not. m->lUnChanged,.f.,;
- iif(&array1.[m->nArIndex]=;
- &array2.[m->nArIndex],.t.,.f.))
- m->nArIndex=m->nArIndex-1
- enddo
-
- m->nArIndex=m->nOrgInd && Originalwert mu· wiederhergestellt werden,
- && sonst Åbergibt das Programm 0
-
- RETURN
- *-- EoF: CmpArray
-
- FUNCTION ARec2Arr
- *-----------------------------------------------------------------------
- *-- Programmer..: Bowen Moursund (CIS: 72662,436)
- *-- Date........: 05/01/1993
- *-- Notes.......: Creates a public array, &aRecord.[n], initialized to
- *-- the record format of the currently selected DBF,
- *-- either blank or filled with the values of the current
- *-- record. Memo fields cannot be copied to an array.
- *-- Written for.: dBASE IV v1.5
- *-- Rev. History: 05/01/1992 -- Original
- *-- 05/01/1993 modified by Werner Borsbach
- *-- (CIS: 100010,2236) - name of array is to be chosen
- *-- when the function is called so that one now can
- *-- create multiple arrays and compare them.
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: Arec2Arr(<aRecord>,[<lBlank>])
- *-- Example.....: lSuccess = Arec2Arr("data")
- *-- Returns.....: .T. if succesful, .F. if not.
- *-- Parameters..: aRecord = name of array
- *-- lBlank = whether or not to create an empty array.
- *-- .T. = blank
- *-- .F. = current record values
- *-- Side effects: Creates a public array, &aRecord.[n]. It will destroy
- *-- an existing array of that name
- *-----------------------------------------------------------------------
-
- parameters aRecord,lBlank
- private lSuccess,lDbf,cFieldName,nFieldNumb,nNumFields
-
- m->lSuccess = .f.
- m->lDBF = ( "" # dbf() )
- if ((m->lDBF .and. m->lBlank) .or. (.not. m->lBlank .and. m->lDBF ;
- .and. .not. eof()))
- release &aRecord.
- m->nNumFields = fldcount()
- public array &aRecord.[m->nNumFields]
- if m->lBlank
- goto bottom
- skip && phantom record
- m->nFieldNumb=1
- do while m->nFieldNumb <= m->nNumFields
- m->cFieldName = field(m->nFieldNumb)
- store &cFieldName. to &aRecord.[m->nFieldNumb]
- m->nFieldNumb = m->nFieldNumb + 1
- enddo
- else
- copy to array &aRecord. next 1
- endif
- m->lSuccess = .t.
- endif
-
- RETURN m->lSuccess
- *-- EoF: Arec2Arr()
-
- *-----------------------------------------------------------------------
- *-- The following are routines to manipulate a stack.
- *--
- *-- stack: INDEX STACK ELEMENTS
- *-- |--------------------|
- *-- 1 | Size of Stack |
- *-- |--------------------|
- *-- 2 | Top of Stack (TOS) |
- *-- |--------------------|
- *-- 3 | First Element |
- *-- |--------------------|
- *-- | |
- *--
- *-- | |
- *-- |--------------------|
- *-- TOS | Top Element |
- *-- |--------------------|
- *--
- *-----------------------------------------------------------------------
-
- FUNCTION StackNew
- *-----------------------------------------------------------------------
- *-- Programmer..: Frank A. Deviney, Jr. (CIS: 72357,345)
- *-- Date........: 07/15/93
- *-- Notes.......: Creates a new stack. This is not a true stack since it
- *-- is limited in size.
- *--
- *-- &cName.[1] = maximum size of stack
- *-- &cName.[2] = top of stack pointer value
- *--
- *-- For large stacks it may be necessary to increase
- *-- memory variable space (for the other memvars)
- *-- Written for.: dBASE IV, v2.0
- *-- Rev. History: 07/15/1993 - Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: ? StackNew(<cName>, <nSize>)
- *-- Example.....: lError = StackNew("stack1",100)
- *-- Returns.....: .t. if stack created, else .f.
- *-- Parameters..: cName = name of stack
- *-- nSize = size of stack
- *-- Side Effect.: Changes setting for ON ERROR
- *-----------------------------------------------------------------------
-
- parameters cName, nSize
-
- private m->lRet
-
- m->lRet = .t.
- on error m->lRet = .f.
- public array &cName.[nSize+2] && fails if size too big for version
- on error
- if m->lRet
- store nSize to &cName.[1] && initialize stack header info
- store 3 to &cName.[2]
- endif
-
- RETURN m->lRet
- *-- EoF: StackNew()
-
- FUNCTION StackEmpty
- *-----------------------------------------------------------------------
- *-- Programmer..: Frank A. Deviney, Jr. (CIS: 72357,345)
- *-- Date........: 07/16/1993
- *-- Notes.......: Checks if stack is empty.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 06/16/1993 -- Original
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: StackEmpty(<cName>)
- *-- Example.....: lError = StackEmpty("mystack")
- *-- Returns.....: .t. if stack is empty, .f. otherwise
- *-- Parameters..: cName = name of stack
- *-----------------------------------------------------------------------
-
- parameters cName
-
- RETURN (&cName.[2] <= 3)
- *-- EoF: StackEmpty()
-
- FUNCTION StackFull
- *-----------------------------------------------------------------------
- *-- Programmer..: Frank A. Deviney, Jr. (CIS: 72357,345)
- *-- Date........: 07/16/1993
- *-- Notes.......: Stack is full if top_of_stack pointer is one beyond the
- *-- stack size.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 07/16/1993 -- Original
- *-- Calls.......: None
- *-- Called by...: StackPush()
- *-- Usage.......: StackFull(<cName>)
- *-- Example.....: lError = StackFull("mystack")
- *-- Returns.....: .t. if stack is full, .f. otherwise
- *-- Parameters..: cName = name of stack
- *-----------------------------------------------------------------------
-
- parameters cName
-
- RETURN (&cName.[2] >= &cName.[1]+3)
- *-- EoF: StackFull()
-
- FUNCTION StackPush
- *-----------------------------------------------------------------------
- *-- Programmer..: Frank A. Deviney, Jr. (CIS: 72357,345)
- *-- Date........: 07/17/1993
- *-- Notes.......: Adds an element to the stack. Stack elements can be of
- *-- any type.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 07/17/1993 -- Original
- *-- Calls.......: StackFull()
- *-- Called by...: Any
- *-- Usage.......: StackPush(<cName>,<xElement>)
- *-- Example.....: lError = StackPush("mystack", cWord)
- *-- Returns.....: .t. if the element was added (stack must not be full)
- *-- Parameters..: cName = name of stack
- *-- xElement = element to add to stack
- *-----------------------------------------------------------------------
-
- parameters cName, xElement
- private lRet, nTOS
-
- if .not. StackFull(m->cName)
- m->nToS = &cName.[2] && get top of stack
- store m->xElement to &cName.[m->nToS] && add element
- store m->nToS+1 to &cName.[2] && increment top of
- && stack pointer
- m->lRet = .t.
- else
- m->lRet = .f.
- endif
-
- RETURN m->lRet
- *-- EoF: StackPush()
-
- FUNCTION StackPop
- *-----------------------------------------------------------------------
- *-- Programmer..: Frank A. Deviney, Jr. (CIS: 72357,345)
- *-- Date........: 07/16/1993
- *-- Notes.......: Remove an element from the stack (if stack not empty).
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 07/16/1993 -- Original
- *-- Calls.......: StackEmpty()
- *-- Called by...: Any
- *-- Usage.......: StackPop(<cName>, <xElement>)
- *-- Example.....: lError = StackPop("mystack", cWord)
- *-- Returns.....: .t. if an element was remove, .f. if stack was empty
- *-- Parameters..: cName = name of stack
- *-- xElement = receptacle for the top element
- *-----------------------------------------------------------------------
-
- parameters cName, xElement
- private lRet
-
- if .not. StackEmpty(m->cName)
- store &cName.[2]-1 to &cName.[2] && decrement stack pointer
- m->xElement = &cName.[&cName.[2]] && pop element
- m->lRet = .t.
- else
- m->lRet = .f.
- endif
-
- RETURN m->lRet
- *-- EoF: StackPop()
-
- FUNCTION StackTop
- *-----------------------------------------------------------------------
- *-- Programmer..: Frank A. Deviney, Jr. (CIS: 72357,345)
- *-- Date........: 07/16/1993
- *-- Notes.......: Assigns element on top of stack without removing it.
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 07/16/1993 -- Original
- *-- Calls.......: StackEmpty()
- *-- Called by...: Any
- *-- Usage.......: StackTop(<cName>,<xElement>)
- *-- Example.....: lError = StackTop("mystack", cWord)
- *-- Returns.....: .t. if stack was not empty, else .f.
- *-- Parameters..: cName = name of stack
- *-- xElement = receptacle for top element on stack
- *-----------------------------------------------------------------------
-
- parameters cName, xElement
- private lRet
-
- if .not. StackEmpty(cName)
- m->xElement = &cName.[&cName.[2]-1] && show top element
- m->lRet = .t. && leave top of stack
- else && pointer alone
- m->lRet = .f.
- endif
-
- RETURN m->lRet
- *-- EoF: StackTop()
-
- PROCEDURE StackDelete
- *-----------------------------------------------------------------------
- *-- Programmer..: Frank A. Deviney, Jr. (CIS: 72357,345)
- *-- Date........: 07/17/1993
- *-- Notes.......: Releases memory held by a stack
- *-- Written for.: dBASE IV, 2.0
- *-- Rev. History: 07/17/1993 -- Original Release
- *-- Calls.......: None
- *-- Called by...: Any
- *-- Usage.......: StackDelete with <cName>
- *-- Example.....: do StackDelete with "mystack"
- *-- Returns.....: n/a
- *-- Parameters..: cName = name of stack
- *-----------------------------------------------------------------------
-
- parameters cName
-
- release &cName.
-
- RETURN
- *-- EoP: StackDelete
-
- *-----------------------------------------------------------------------
- *-- EoP: ARRAY.PRG
- *-----------------------------------------------------------------------
-